
#include <boost/lexical_cast.hpp>
#include <string>
#include <vector>
#include <json/json.h>
#include "../activite/webcollector.h"
#include "../core/operator_message.h"
#include "../core/cookiejar.h"
#include "webspidercustom.h"

#include <QDebug>

using namespace boost;
using namespace std;

WebSpider::WebSpider(ProcessRouter::Channel *channel)
    : CommunKit(channel)
    , m_killed(false)
    , m_logger(Log4Qt::Logger::logger("WebSpider"))
{
}

WebSpider::~WebSpider()
{
}

void WebSpider::setName(QString name)
{
    m_name = name;
}

void WebSpider::removeSuccessOpt(Operator *opt)
{
    if (m_successOpt.contains(opt))
        m_successOpt.removeOne(opt);
}

bool WebSpider::parse(Operator *opt)
{
    QString clientidGet;
    QString syncLoad;
    QString clientidRawPage;
    QMap<QString, QString> resultMap;

    // If has prase and handled.
    if (opt->isParseSuccess())
        return true;

    WebSpiderRequest *req = opt->request();
    if (m_getReqMap.contains(req))
        clientidGet = m_getReqMap.value(req);
    
    if (m_syncLoadMap.contains(opt))
        syncLoad = m_syncLoadMap.value(opt);

    if (opt->rawPageFlag())
        clientidRawPage = m_syncRawPageLoadMap.value(opt->rawPageFlag());

    QString logMessage;

    if (!opt->loadSuccess()) {
        QString logMessage = protocol() + " | failed loaded url :" + opt->getUrl();
        m_logger->info(logMessage);

        if (opt->httpRequestCanceled())
            resultMap.insert("error", QString::number(-5));
        else if (opt->hostNotFound())
            resultMap.insert("error", QString::number(-3));
        else if (opt->netWorkError())
            resultMap.insert("error", QString::number(-99));
        else if (opt->protocolUnknown())
            resultMap.insert("error", QString::number(-301));
        else if (opt->isTimeout())
            resultMap.insert("error", QString::number(-6));
        else
            resultMap.insert("error", QString::number(opt->errorCode()));

        if (!clientidGet.isNull()) {
            m_getReqMap.remove(opt->request());

            // because page while be remove, return 0.
            resultMap.insert("page", QString::number(0));

            // Don't let the client call function of the page which is normal page and load fail.
            removeSuccessOpt(opt);

            sendReturnJson(clientidGet, 0, OPERATOR_LONG_GET_LONG_REF_STRING_URL, mapToJsonString(resultMap));
            opt->setParseSuccess();
            if (opt->isTimeout())
                opt->remove();

            logMessage = protocol() + " | loaded failed: " + opt->getUrl();
            m_logger->info(logMessage);
        }

        if (!clientidRawPage.isNull()) {
            m_syncRawPageLoadMap.remove(opt->rawPageFlag());

            if (opt->isTimeout()) {
                logMessage = protocol() + " | return page id " + QString::number((long)opt);
                m_logger->info(logMessage);
                // because the page is already be constructed, return page id and push the page into success opt list.
                resultMap.insert("page", QString::number((long)opt));
                if (!m_successOpt.contains(opt))
                    m_successOpt.push_back(opt);
            } else
                resultMap.insert("page", QString::number(0));

            sendReturnJson(clientidRawPage, 0, OPERATOR_LONG_CLICK_LONG_REF, mapToJsonString(resultMap));
            opt->setParseSuccess();

            logMessage = protocol() + " | raw page load return url failed: " + opt->getUrl();
            m_logger->info(logMessage);
        }

        if (!syncLoad.isNull()) {
            m_syncLoadMap.remove(opt);

            // because the page is already be constructed, return page id.
            resultMap.insert("page", QString::number((long)opt));

            sendReturnJson(syncLoad, 0, OPERATOR_LONG_CLICK_LONG_REF, mapToJsonString(resultMap));
            opt->setParseSuccess();

            logMessage = protocol() + " | sync load return url failed: " + opt->getUrl();
            m_logger->info(logMessage);
        }

        return false;
    }

    logMessage = protocol() + " | success loaded url :" + opt->getUrl();
    m_logger->info(logMessage);

    // success, return error=0 and page id.
    resultMap.insert("error", QString::number(0));
    resultMap.insert("page", QString::number(long(opt)));
    if (!clientidGet.isNull()) {
        logMessage = protocol() + " | loaded return url :" + opt->getUrl();
        m_logger->info(logMessage);
        sendReturnJson(clientidGet, long(opt), OPERATOR_LONG_GET_LONG_REF_STRING_URL, mapToJsonString(resultMap));
        m_getReqMap.remove(opt->request());
    }

    else if (!clientidRawPage.isNull()) {
        logMessage = protocol() + " | raw page load return url :" + opt->getUrl();
        m_logger->info(logMessage);
        sendReturnJson(clientidRawPage, long(opt), OPERATOR_LONG_CLICK_LONG_REF, mapToJsonString(resultMap));
        m_syncRawPageLoadMap.remove(opt->rawPageFlag());
    }

    else if (!syncLoad.isNull()) {
        logMessage = protocol() + " | sync load return url :" + opt->getUrl();
        m_logger->info(logMessage);
        sendReturnJson(syncLoad, long(opt), OPERATOR_LONG_CLICK_LONG_REF, mapToJsonString(resultMap));
        m_syncLoadMap.remove(opt);
    }

    else {
        if (m_successOpt.contains(opt)) {
            QString logMessage = "Unknow request page : " + opt->getUrl();
            m_logger->warn(logMessage);
            opt->setParseSuccess();
        } else {
            QString logMessage = "Unknow source page : " + opt->getUrl();
            m_logger->warn(logMessage);
        }
        return false;
    }

    if (!m_successOpt.contains(opt))
        m_successOpt.push_back(opt);

    opt->setParseSuccess();

    return true;
}

bool WebSpider::rawPageError(Operator *opt)
{
    QString clientidGet;
    QString syncLoad;
    QString clientidRawPage;

    if (!opt->loadSuccess()) {
        if (opt->rawPageFlag())
            clientidRawPage = m_syncRawPageLoadMap.value(opt->rawPageFlag());

        if (!clientidRawPage.isNull()) {
            m_syncRawPageLoadMap.remove(opt->rawPageFlag());

            QMap<QString, QString> resultMap;
            // send -7, raw page time out error.
            resultMap.insert("error", QString::number(-7));
            resultMap.insert("page", QString::number(0));

            sendReturnJson(clientidRawPage, 0, OPERATOR_LONG_CLICK_LONG_REF, mapToJsonString(resultMap));

            QString logMessage = protocol() + " | raw page load return url failed: " + opt->getUrl();
            m_logger->info(logMessage);
        }

        return true;
    }

    return false;
}

bool WebSpider::sendDownloadInfo(Operator *opt)
{
    WebSpiderDownloadRequest *req = opt->getDownloadRequest();
    if (!req)
        return false;

    if (req->success())
        sendReturnJson(req->clientID(), 0, OPERATOR_LONG_DOWNLOAD_LONG_REF, getDownloadInfoJson(req));
    else
        sendReturnJson(req->clientID(), 0, OPERATOR_LONG_DOWNLOAD_LONG_REF, "");

    opt->clearDownloadRequest();
    delete req;
    return true;
}

QString WebSpider::getDownloadInfoJson(WebSpiderDownloadRequest *req)
{
    Json::FastWriter writer;
    Json::Value root(Json::objectValue);
    Json::Value headers(Json::arrayValue);

    root["link"] = req->link().toLatin1().constData();

    QVariantList headerList = req->headers();

    QVariantList::iterator it;
    for (it = headerList.begin(); it != headerList.end(); it++) {
        Json::Value header(Json::objectValue);
        QVariantMap map = it->toMap();
        QVariantMap::iterator it;
        for (it = map.begin(); it != map.end(); it ++) {
            header[it.key().toLatin1().constData()] = Json::Value(it.value().toString().toLatin1().constData());
        }
        headers.append(header);
    }

    root["headers"] = headers;

    std::string jsonStr = writer.write(root);
    return jsonStr.c_str();

}

void WebSpider::destroy()
{
    CommunKit::destroy();
    m_killed = true;
}

void WebSpider::taskLoop()
{
    std::list<std::string> messlist = recvNoWait();

    std::list<std::string>::iterator it;
    for (it = messlist.begin(); it != messlist.end(); it++)
        parseAndCallFunc((*it).c_str());
}

QString WebSpider::arrayToJson(QList<long> arr)
{
    QString array = "{\"array\":[";
    for (int i = 0; i < arr.size(); i ++) {
        array.append("\""+QString::number(arr.at(i))+"\"");
        if (i != arr.size() - 1)
            array.append(",");
    }
    array.append("]}");
    return array;
}

void WebSpider::jsonToList(QString jsonString, QList<QString> &result)
{
    if (jsonString == "")
        return;

    Json::Reader reader;
    Json::Value value(Json::arrayValue);

    if (!reader.parse(jsonString.toLatin1().constData(), value))
        return ;

    for (int i = 0; i < value.size(); i ++) {
        if (value[i].isString())
            result.push_back(value[i].asCString());
    }
}

void WebSpider::jsonStringToQMap(QString jsonString, QMap<QString, QString> &map)
{
    if (jsonString == "")
        return;

    Json::Reader reader;
    Json::Value value;

    if (!reader.parse(jsonString.toLatin1().constData(), value))
        return ;

    Json::Value::Members member;
    for (int i = 0; i < value.size(); i ++)
    {
        member = value[i].getMemberNames();
        for (Json::Value::Members::iterator iter = member.begin(); iter != member.end(); iter++)
        {
            std::string val = value[i][(*iter)].asString();
            map.insert((*iter).c_str(), val.c_str());
        }
    }
}

QString WebSpider::mapToJsonString(QMap<QString, QString> &map)
{
    Json::FastWriter writer;
    Json::Value root(Json::objectValue);

    QMap<QString, QString>::iterator it;
    for (it = map.begin(); it != map.end(); it ++) {
        root[it.key().toLatin1().constData()] = Json::Value(it.value().toLatin1().constData());
    }

    std::string jsonStr = writer.write(root);
    return jsonStr.c_str();
}

void WebSpider::jsonToVariantMapList(QString jsonString, QVariantList &variantList)
{
    if (jsonString == "")
        return;

    Json::Reader reader;
    Json::Value value;

    if (!reader.parse(jsonString.toLatin1().constData(), value))
        return ;
    QMap<QString, QVariant> map;
    Json::Value::Members member;
    for (int i = 0; i < value.size(); i ++)
    {
        Json::Value element = value[i];
        member = element.getMemberNames();
        for (Json::Value::Members::iterator iter = member.begin(); iter != member.end(); iter++)
        {
            Json::Value baseValue = element[*iter];
            if (baseValue.isString()) {
                std::string val = element[*iter].asString();
                QVariant variant(QString(val.c_str()));
                map.insert((*iter).c_str(), variant);
            } else if (baseValue.isDouble()) {
                double val = element[*iter].asDouble();
                QVariant variant(val);
                map.insert((*iter).c_str(), variant);
            } else if (baseValue.isBool()) {
                bool val = element[*iter].asDouble();
                QVariant variant(val);
                map.insert((*iter).c_str(), variant);
            } else if (baseValue.isInt()) {
                int val = element[*iter].asDouble();
                QVariant variant(val);
                map.insert((*iter).c_str(), variant);
            }
        }
        variantList.append(map);
    }
}

QString WebSpider::variantMapListToJson(QVariantList var)
{
    QString rectJson;
    Json::FastWriter writer;
    Json::Value root(Json::arrayValue);

    for (int i = 0; i < var.size(); i ++) {
        QMap<QString, QVariant> mvar = var.at(i).toMap();
        QList<QString> mvarKeys = mvar.keys();
        Json::Value jvalue(Json::objectValue);
        for (int j = 0; j < mvarKeys.size(); j ++) {
            QVariant value = mvar[mvarKeys.at(j)];
            if (value.type() == QVariant::Bool) {
                jvalue[mvarKeys.at(j).toLatin1().constData()] = Json::Value(value.toBool());
            } else if (value.type() == QVariant::Double) {
                double baseValue = value.toDouble();
                jvalue[mvarKeys.at(j).toLatin1().constData()] = Json::Value(baseValue);
            } else if (value.type() == QVariant::LongLong) {
                double baseValue = value.toLongLong();
                jvalue[mvarKeys.at(j).toLatin1().constData()] = Json::Value(baseValue);
            } else if (value.type() == QVariant::String) {
                jvalue[mvarKeys.at(j).toLatin1().constData()] = Json::Value(value.toString().toLatin1().constData());
            }
        }
        root.append(jvalue);
    }

    rectJson = writer.write(root).c_str();
    return rectJson;
}

void WebSpider::loadUrl(std::string clientid, QList<std::string> &argstrs)
{
    QMap<QString, QString> resultMap;
    resultMap.insert("page", QString::number(0));

    if (argstrs.size() < 4) {
        resultMap.insert("error", QString::number(-1));
        sendReturnJson(clientid.c_str(), 0, OPERATOR_VOID_LOADURL_LONG_REF_STRING_ADDRESS_STRING_OPERATION_QMAP_STRING_STRING_HEADERS_STRING_BODYSTRING_STRING_ENCODING, mapToJsonString(resultMap));
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    QMap<QString, QString> headers;
    long ref = 0;
    bool ok;
    bool sync = false;
    ref = arg0.toLong(&ok);
    sync = QString(argstrs.at(1).c_str()).toLong(&ok) == 0 ? false : true;

    Operator *opt = (Operator*)ref;

    if (!opt || !m_successOpt.contains(opt)) {
        resultMap.insert("error", QString::number(-1));
        sendReturnJson(clientid.c_str(), 0, OPERATOR_VOID_LOADURL_LONG_REF_STRING_ADDRESS_STRING_OPERATION_QMAP_STRING_STRING_HEADERS_STRING_BODYSTRING_STRING_ENCODING, mapToJsonString(resultMap));
        return;
    }

    if (sync) {
        m_syncLoadMap.insert(opt, clientid.c_str());
        opt->clearParseSuccess();
        opt->setSyncLoad();
        opt->clearParsed();
    }

    if (argstrs.size() == 4)
        opt->loadUrl(QString(argstrs.at(2).c_str()), QString(argstrs.at(3).c_str()), headers);
    else if (argstrs.size() == 5) {
        jsonStringToQMap(QString(argstrs.at(4).c_str()), headers);
        opt->loadUrl(QString(argstrs.at(2).c_str()), QString(argstrs.at(3).c_str()), headers);
    } else if (argstrs.size() == 7) {
        jsonStringToQMap(QString(argstrs.at(4).c_str()), headers);
        opt->loadUrl(QString(argstrs.at(2).c_str()), QString(argstrs.at(3).c_str()), headers, QString(argstrs.at(5).c_str()), QString(argstrs.at(6).c_str()));
    } else if (argstrs.size() == 8) {
        jsonStringToQMap(QString(argstrs.at(4).c_str()), headers);
        QString timeout(argstrs.at(7).c_str());
        int time = timeout.toLong(&ok);
        opt->loadUrl(QString(argstrs.at(2).c_str()), QString(argstrs.at(3).c_str()), headers, QString(argstrs.at(5).c_str()), QString(argstrs.at(6).c_str()), time);
    } else if (argstrs.size() == 9) {
        jsonStringToQMap(QString(argstrs.at(4).c_str()), headers);
        QString timeout = argstrs.at(7).c_str();
        QString dtimeout = argstrs.at(8).c_str();
        int time = timeout.toLong(&ok);
        int dtime = dtimeout.toLong(&ok);
        opt->loadUrl(QString(argstrs.at(2).c_str()), QString(argstrs.at(3).c_str()), headers, QString(argstrs.at(5).c_str()), QString(argstrs.at(6).c_str()), time, dtime);
    }

    if (!sync) {
        resultMap.insert("error", QString::number(1));
        sendReturnJson(clientid.c_str(), ref, OPERATOR_VOID_LOADURL_LONG_REF_STRING_ADDRESS_STRING_OPERATION_QMAP_STRING_STRING_HEADERS_STRING_BODYSTRING_STRING_ENCODING, mapToJsonString(resultMap));
    }
}

void WebSpider::setHtml(std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 3) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_VOID_SETHTML_LONG_REF_STRING_HTML, QString::number(-1));
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    QString arg1 = argstrs.at(1).c_str();
    QString arg2 = argstrs.at(2).c_str();
    long ref = 0;
    bool ok;

    ref = arg0.toLong(&ok);
    Operator *opt = (Operator*)ref;

    if (!opt || !m_successOpt.contains(opt)) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_VOID_SETHTML_LONG_REF_STRING_HTML, QString::number(-1));
        return;
    }

    opt->setHtml(arg1, arg2);
    sendReturnJson(clientid.c_str(), ref, OPERATOR_VOID_SETHTML_LONG_REF_STRING_HTML, QString::number(0));
}

void WebSpider::setSetting(std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 3) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_VOID_SETSETTING_LONG_REF_STRING_NAME_STRING_SETTING, QString::number(-1));
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    QString arg1 = argstrs.at(1).c_str();
    QString arg2 = argstrs.at(2).c_str();
    long ref = 0;
    bool ok;

    ref = arg0.toLong(&ok);
    Operator *opt = (Operator*)ref;

    if (!opt || !m_successOpt.contains(opt)) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_VOID_SETSETTING_LONG_REF_STRING_NAME_STRING_SETTING, QString::number(-1));
        return;
    }

    opt->setSetting(arg1, arg2);
    sendReturnJson(clientid.c_str(), ref, OPERATOR_VOID_SETSETTING_LONG_REF_STRING_NAME_STRING_SETTING, QString::number(0));
}

void WebSpider::destroy(std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 1) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_DESTROY_LONG_REF, QString::number(-1));
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    long ref = 0;
    bool ok;
    ref = arg0.toLong(&ok);
    Operator *opt = (Operator*)ref;

    if (!opt || !m_successOpt.contains(opt)) {
        sendReturnJson(clientid.c_str(), long(opt), OPERATOR_LONG_DESTROY_LONG_REF, QString::number(-1));
        return;
    }

    m_successOpt.removeOne(opt);

    // 先返回删除成功消息，webkit避免提前退出，无法返回消息
    sendReturnJson(clientid.c_str(), long(opt), OPERATOR_LONG_DESTROY_LONG_REF, QString::number(0));

    opt->remove();
}

void WebSpider::get(std::string clientid, QList<std::string> &argstrs)
{
    QMap<QString, QString> resultMap;
    resultMap.insert("page", QString::number(0));
    // return -2, when spider was refresh and wait all task to compeled.
    if (m_killed) {
        resultMap.insert("error", QString::number(-2));
        QString logMessage = protocol() + " | be killed, return -2. ";
        m_logger->info(logMessage);
        sendReturnJson(clientid.c_str(), 0, 0, mapToJsonString(resultMap));
        return;
    }

    if (argstrs.size() < 2) {
        resultMap.insert("error", QString::number(-1));
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_GET_LONG_REF_STRING_URL, mapToJsonString(resultMap));
        return;
    }
    WebSpiderRequest *req = NULL;

    QString arg1 = argstrs.at(1).c_str();

    QVariantList cookies;
    QString cookiestr = QString::fromUtf8(argstrs.at(2).c_str(), argstrs.at(2).size());
    jsonToVariantMapList(cookiestr, cookies);

    if (argstrs.size() == 4) {
        QString level = argstrs.at(3).c_str();
        try {
            long ret = boost::lexical_cast<long>(level.toLatin1().constData());
            req = WebSpiderRequestManager::instance()->startRequest(arg1, m_name, cookies, ret);
        } catch(boost::exception& e) {
            req = WebSpiderRequestManager::instance()->startRequest(arg1, m_name, cookies);
        }
    } else if (argstrs.size() == 5) {
        QString level = argstrs.at(3).c_str();
        QString time = argstrs.at(4).c_str();
        try {
            long ret = boost::lexical_cast<long>(level.toLatin1().constData());
            long timeMS = boost::lexical_cast<long>(time.toLatin1().constData());
            req = WebSpiderRequestManager::instance()->startRequest(arg1, m_name, cookies, ret, timeMS);
        } catch(boost::exception& e) {
            req = WebSpiderRequestManager::instance()->startRequest(arg1, m_name, cookies);
        }
    } else if (argstrs.size() == 6) {
        QString level = argstrs.at(3).c_str();
        QString time = argstrs.at(4).c_str();
        QString dtime = argstrs.at(5).c_str();
        try {
            long ret = boost::lexical_cast<long>(level.toLatin1().constData());
            long timeMS = boost::lexical_cast<long>(time.toLatin1().constData());
            long dtimeMS = boost::lexical_cast<long>(dtime.toLatin1().constData());
            req = WebSpiderRequestManager::instance()->startRequest(arg1, m_name, cookies, ret, timeMS, dtimeMS);
        } catch(boost::exception& e) {
            req = WebSpiderRequestManager::instance()->startRequest(arg1, m_name, cookies);
        }
    } else {
        req = WebSpiderRequestManager::instance()->startRequest(arg1, m_name, cookies);
    }
    if (req) {
        req->setClientID(clientid);
        m_getReqMap.insert(req, QString(clientid.c_str()));
    }
}

void WebSpider::setDatabaseEnabled(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 2) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_BOOL_SETDATABASEENABLED_LONG_REF_BOOL_ENABLE, QString::number(-1));
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    QString arg1 = argstrs.at(1).c_str();
    long ref = 0;
    long enable = 0;
    bool ok;

    ref = arg0.toLong(&ok);
    enable = arg1.toLong(&ok);

    if (!opt || !m_successOpt.contains(opt)) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_BOOL_SETDATABASEENABLED_LONG_REF_BOOL_ENABLE, QString::number(-1));
        return;
    }

    opt->setDatabaseEnabled(ref, enable);
    sendReturnJson(clientid.c_str(), ref, OPERATOR_BOOL_SETDATABASEENABLED_LONG_REF_BOOL_ENABLE, QString::number(0));
}

void WebSpider::getTitle(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 1) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_STRING_GETTITLE_LONG_REF, "");
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    long ref = 0;
    bool ok;

    ref = arg0.toLong(&ok);

    if (!opt || !m_successOpt.contains(opt)) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_STRING_GETTITLE_LONG_REF, "");
        return;
    }

    QString title = opt->getTitle(ref);
    sendReturnJson(clientid.c_str(), ref, OPERATOR_STRING_GETTITLE_LONG_REF, title);
}

void WebSpider::renderTreeDump(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 1) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_STRING_RENDERTREEDUMP_LONG_REF, "");
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    long ref = 0;
    bool ok;

    ref = arg0.toLong(&ok);

    if (!opt || !m_successOpt.contains(opt)) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_STRING_RENDERTREEDUMP_LONG_REF, "");
        return;
    }

    QString dumpTree = opt->renderTreeDump(ref);
    sendReturnJson(clientid.c_str(), ref, OPERATOR_STRING_RENDERTREEDUMP_LONG_REF, dumpTree);
}

void WebSpider::getPageSource(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 1) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_STRING_GETPAGESOURCE_LONG_REF, "");
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    long ref = 0;
    bool ok;

    ref = arg0.toLong(&ok);

    if (!opt || !m_successOpt.contains(opt)) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_STRING_GETPAGESOURCE_LONG_REF, "");
        return;
    }

    QString source = opt->getPageSource(ref);
    sendReturnJson(clientid.c_str(), ref, OPERATOR_STRING_GETPAGESOURCE_LONG_REF, source);
}

void WebSpider::getUrl(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 1) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_STRING_GETURL_LONG_REF, "");
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    long ref = 0;
    bool ok;

    ref = arg0.toLong(&ok);

    if (!opt || !m_successOpt.contains(opt)) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_STRING_GETURL_LONG_REF, "");
        return;
    }

    QString url = opt->getUrl(ref);
    sendReturnJson(clientid.c_str(), ref, OPERATOR_STRING_GETURL_LONG_REF, url);
}

void WebSpider::getElementById(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 2) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_GETELEMENTBYID_LONG_REF_STRING_QUERY, QString::number(-1));
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    QString arg1 = argstrs.at(1).c_str();
    long ref = 0;
    bool ok;

    ref = arg0.toLong(&ok);

    if (!opt || !m_successOpt.contains(opt)) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_GETELEMENTBYID_LONG_REF_STRING_QUERY, QString::number(-1));
        return;
    }

    long element = opt->getElementById(ref, arg1);
    sendReturnJson(clientid.c_str(), ref, OPERATOR_LONG_GETELEMENTBYID_LONG_REF_STRING_QUERY, QString::number(element));
}

void WebSpider::setCookies(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 2) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_SETCOOKIE_LONG_REF_STRING_COOKIES, QString::number(-1));
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    QString cookiestr = QString::fromUtf8(argstrs.at(1).c_str(), argstrs.at(1).size());
    QVariantList cookies;
    long ref = 0;
    bool ok;

    ref = arg0.toLong(&ok);

    if (!opt || !m_successOpt.contains(opt)) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_SETCOOKIE_LONG_REF_STRING_COOKIES, QString::number(-1));
        return;
    }

    jsonToVariantMapList(cookiestr, cookies);

    long ret = opt->setCookies(ref, cookies);
    sendReturnJson(clientid.c_str(), ref, OPERATOR_LONG_SETCOOKIE_LONG_REF_STRING_COOKIES, QString::number(ret));
}

void WebSpider::cookies(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 1) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_STRING_COOKIES_LONG_REF, "[]");
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    long ref = 0;
    bool ok;

    ref = arg0.toLong(&ok);

    if (!opt || !m_successOpt.contains(opt)) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_STRING_COOKIES_LONG_REF, "[]");
        return;
    }

    QVariantList cookies = opt->cookies(ref);
    QString cookie = variantMapListToJson(cookies);
    sendReturnJson(clientid.c_str(), ref, OPERATOR_STRING_COOKIES_LONG_REF, cookie);
}

void WebSpider::setFilterRule(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 1) {
        RETURN_VOID(clientid.c_str());
        return;
    }


    if (!opt || !m_successOpt.contains(opt)) {
        RETURN_VOID(clientid.c_str());
        return;
    }

    QList<QString> filterRules;
    QString filterRulesStr = argstrs.at(0).c_str();
    jsonToList(filterRulesStr, filterRules);

    opt->setFilterRule(filterRules);
    RETURN_VOID(clientid.c_str());
}

void WebSpider::setCookiesWithUrl(std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 2) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_SETCOOKIE_LONG_REF_STRING_COOKIES_STRING_URL, QString::number(-1));
        return;
    }

    QString cookiestr = QString::fromUtf8(argstrs.at(0).c_str(), argstrs.at(0).size());
    QString url = QString::fromUtf8(argstrs.at(1).c_str(), argstrs.at(1).size());
    QVariantList cookies;

    jsonToVariantMapList(cookiestr, cookies);

    // Delete all the cookies for this URL
    CookieJar::instance()->deleteCookies(url);
    // Add a new set of cookies for this URL
    CookieJar::instance()->addCookiesFromMap(cookies, url);

    sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_SETCOOKIE_LONG_REF_STRING_COOKIES_STRING_URL, QString::number(1));
}

void WebSpider::deleteCookie(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 2) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_DELETECOOKIE_LONG_REF_STRING_CNAME, QString::number(-1));
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    QString arg1 = QString::fromUtf8(argstrs.at(1).c_str(), argstrs.at(1).size());
    long ref = 0;
    bool ok;

    ref = arg0.toLong(&ok);

    if (!opt || !m_successOpt.contains(opt)) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_DELETECOOKIE_LONG_REF_STRING_CNAME, QString::number(-1));
        return;
    }

    long ret = opt->deleteCookie(ref, arg1);
    sendReturnJson(clientid.c_str(), ref, OPERATOR_LONG_DELETECOOKIE_LONG_REF_STRING_CNAME, QString::number(ret));
}

void WebSpider::getElementsByTagName(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 2) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_GETELEMENTSBYTAGNAME_LONG_REF_STRING_QUERY, arrayToJson(QList<long>()));
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    QString arg1 = QString::fromUtf8(argstrs.at(1).c_str(), argstrs.at(1).size());
    long ref = 0;
    bool ok;

    ref = arg0.toLong(&ok);

    if (!opt || !m_successOpt.contains(opt)) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_GETELEMENTSBYTAGNAME_LONG_REF_STRING_QUERY, arrayToJson(QList<long>()));
        return;
    }

    sendReturnJson(clientid.c_str(), ref, OPERATOR_LONG_GETELEMENTSBYTAGNAME_LONG_REF_STRING_QUERY, arrayToJson(opt->getElementsByTagName(ref, arg1)));
}

void WebSpider::getElementsByName(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 2) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_GETELEMENTSBYNAME_LONG_REF_STRING_QUERY, arrayToJson(QList<long>()));
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    QString arg1 = QString::fromUtf8(argstrs.at(1).c_str(), argstrs.at(1).size());
    long ref = 0;
    bool ok;

    ref = arg0.toLong(&ok);

    if (!opt || !m_successOpt.contains(opt)) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_GETELEMENTSBYNAME_LONG_REF_STRING_QUERY, arrayToJson(QList<long>()));
        return;
    }

    sendReturnJson(clientid.c_str(), ref, OPERATOR_LONG_GETELEMENTSBYNAME_LONG_REF_STRING_QUERY, arrayToJson(opt->getElementsByName(ref, arg1)));
}

void WebSpider::getElementsByXpath(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 2) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_GETELEMENTSBYXPATH_LONG_REF_STRING_QUERY, arrayToJson(QList<long>()));
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    QString arg1 = QString::fromUtf8(argstrs.at(1).c_str(), argstrs.at(1).size());
    long ref = 0;
    bool ok;

    ref = arg0.toLong(&ok);

    if (!opt || !m_successOpt.contains(opt)) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_GETELEMENTSBYXPATH_LONG_REF_STRING_QUERY, arrayToJson(QList<long>()));
        return;
    }

    sendReturnJson(clientid.c_str(), ref, OPERATOR_LONG_GETELEMENTSBYXPATH_LONG_REF_STRING_QUERY, arrayToJson(opt->getElementsByXpath(ref, arg1)));
}

void WebSpider::getElementByCssSelector(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 2) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_GETELEMENTBYCSSSELECTOR_LONG_REF_STRING_QUERY, QString::number(-1));
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    QString arg1 = QString::fromUtf8(argstrs.at(1).c_str(), argstrs.at(1).size());
    long ref = 0;
    bool ok;
    ref = arg0.toLong(&ok);

    if (!opt || !m_successOpt.contains(opt)) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_GETELEMENTBYCSSSELECTOR_LONG_REF_STRING_QUERY, QString::number(-1));
        return;
    }

    long element = opt->getElementByCssSelector(ref, arg1);
    sendReturnJson(clientid.c_str(), ref, OPERATOR_LONG_GETELEMENTBYCSSSELECTOR_LONG_REF_STRING_QUERY, QString::number(element));
}

void WebSpider::getElementsByCssSelector(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 2) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_GETELEMENTSBYCSSSELECTOR_LONG_REF_STRING_QUERY, arrayToJson(QList<long>()));
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    QString arg1 = QString::fromUtf8(argstrs.at(1).c_str(), argstrs.at(1).size());
    long ref = 0;
    bool ok;
    ref = arg0.toLong(&ok);

    if (!opt || !m_successOpt.contains(opt)) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_GETELEMENTSBYCSSSELECTOR_LONG_REF_STRING_QUERY, arrayToJson(QList<long>()));
        return;
    }

    sendReturnJson(clientid.c_str(), ref, OPERATOR_LONG_GETELEMENTSBYCSSSELECTOR_LONG_REF_STRING_QUERY, arrayToJson(opt->getElementsByCssSelector(ref, arg1)));
}

void WebSpider::getTagName(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 1) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_STRING_GETTAGNAME_LONG_REF, "");
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    long ref = 0;
    bool ok;
    ref = arg0.toLong(&ok);

    if (!opt || !m_successOpt.contains(opt)) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_STRING_GETTAGNAME_LONG_REF, "");
        return;
    }

    QString tagName = opt->getTagName(ref);
    sendReturnJson(clientid.c_str(), ref, OPERATOR_STRING_GETTAGNAME_LONG_REF, tagName);
}

void WebSpider::getAttribute(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 2) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_STRING_GETATTRIBUTE_LONG_REF_STRING_NAME, "");
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    QString arg1 = QString::fromUtf8(argstrs.at(1).c_str(), argstrs.at(1).size());
    long ref = 0;
    bool ok;
    ref = arg0.toLong(&ok);

    if (!opt || !m_successOpt.contains(opt)) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_STRING_GETATTRIBUTE_LONG_REF_STRING_NAME, "");
        return;
    }

    QString attribute = opt->getAttribute(ref, arg1);
    sendReturnJson(clientid.c_str(), ref, OPERATOR_STRING_GETATTRIBUTE_LONG_REF_STRING_NAME, attribute);
}

void WebSpider::getProperty(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 2) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_STRING_GETPROPERTY_LONG_REF_STRING_NAME, "");
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    QString arg1 = QString::fromUtf8(argstrs.at(1).c_str(), argstrs.at(1).size());
    long ref = 0;
    bool ok;
    ref = arg0.toLong(&ok);

    if (!opt || !m_successOpt.contains(opt)) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_STRING_GETPROPERTY_LONG_REF_STRING_NAME, "");
        return;
    }

    QString property = opt->getProperty(ref, arg1);
    sendReturnJson(clientid.c_str(), ref, OPERATOR_STRING_GETPROPERTY_LONG_REF_STRING_NAME, property);
}

void WebSpider::getText(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 1) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_STRING_GETTEXT_LONG_REF, "");
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    long ref = 0;
    bool ok;
    ref = arg0.toLong(&ok);

    if (!opt || !m_successOpt.contains(opt)) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_STRING_GETTEXT_LONG_REF, "");
        return;
    }

    QString text = opt->getText(ref);
    sendReturnJson(clientid.c_str(), ref, OPERATOR_STRING_GETTEXT_LONG_REF, text);
}

void WebSpider::getValue(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 1) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_STRING_GETVALUE_LONG_REF, "");
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    long ref = 0;
    bool ok;
    ref = arg0.toLong(&ok);

    if (!opt || !m_successOpt.contains(opt)) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_STRING_GETVALUE_LONG_REF, "");
        return;
    }

    QString value = opt->getValue(ref);
    sendReturnJson(clientid.c_str(), ref, OPERATOR_STRING_GETVALUE_LONG_REF, value);
}

void WebSpider::sendKeys(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    QMap<QString, QString> resultMap;
    resultMap.insert("page", QString::number(0));

    if (argstrs.size() < 3) {
        resultMap.insert("error", QString::number(-1));
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_SENDKEYS_LONG_REF_STRING_TYPE_LONG_KEYS, mapToJsonString(resultMap));
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    QString arg1 = QString::fromUtf8(argstrs.at(1).c_str(), argstrs.at(1).size());
    QString arg2 = argstrs.at(2).c_str();

    long ref = 0;
    long keys = 0;
    bool ok;
    ref = arg0.toLong(&ok);
    keys = arg2.toLong(&ok);

    if (!opt || !m_successOpt.contains(opt)) {
        resultMap.insert("error", QString::number(-1));
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_SENDKEYS_LONG_REF_STRING_TYPE_LONG_KEYS, mapToJsonString(resultMap));
        return;
    }

    int time = 0;
    int dtime = 0;
    if (argstrs.size() == 6) {
        time = QString(argstrs.at(5).c_str()).toLong(&ok);
    } else if (argstrs.size() == 7) {
        time = QString(argstrs.at(5).c_str()).toLong(&ok);
        dtime = QString(argstrs.at(6).c_str()).toLong(&ok);
    }

    if (argstrs.size() >= 4) {
        bool sync = false;
        QString arg3 = argstrs.at(3).c_str();
        sync = arg3.toLong(&ok) == 0 ? false : true;

        if (sync) {

            bool openNewPage = false;
            if (argstrs.size() >= 5) {
                QString tbk = argstrs.at(4).c_str();
                openNewPage = tbk.toLong(&ok) == 0 ? false : true;
            }

            WebSpiderSyncRequest *req = NULL;
            if (openNewPage) {
                opt->setRawPageFlag();
                req = WebSpiderRequestManager::instance()->createSyncRequest("", m_name, 100, time, dtime);
                m_syncRawPageLoadMap.insert(long(opt), clientid.c_str());
            } else {
                m_syncLoadMap.insert(opt, clientid.c_str());
                opt->clearParseSuccess();
                opt->clearParsed();
                opt->setSyncLoad();
            }
            opt->sendKeys(ref, arg1, keys, time, dtime, req);
        } else {
            long ret = opt->sendKeys(ref, arg1, keys, time);
            resultMap.insert("error", QString::number(ret));
            sendReturnJson(clientid.c_str(), ref, OPERATOR_LONG_SENDKEYS_LONG_REF_STRING_TYPE_LONG_KEYS, mapToJsonString(resultMap));
        }
    } else {
        long ret = opt->sendKeys(ref, arg1, keys, time);
        resultMap.insert("error", QString::number(ret));
        sendReturnJson(clientid.c_str(), ref, OPERATOR_LONG_SENDKEYS_LONG_REF_STRING_TYPE_LONG_KEYS, mapToJsonString(resultMap));
    }
}

void WebSpider::type(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 2) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_TYPE_LONG_REF_STRING_VAL, QString::number(-1));
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    QString arg1 = QString::fromUtf8(argstrs.at(1).c_str(), argstrs.at(1).size());
    long ref = 0;
    bool ok;
    ref = arg0.toLong(&ok);

    if (!opt || !m_successOpt.contains(opt)) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_TYPE_LONG_REF_STRING_VAL, QString::number(-1));
        return;
    }

    long ret = opt->type(ref, arg1);
    sendReturnJson(clientid.c_str(), ref, OPERATOR_LONG_TYPE_LONG_REF_STRING_VAL, QString::number(ret));
}

void WebSpider::setValue(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 2) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_SETVALUE_LONG_REF_STRING_VAL, QString::number(-1));
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    QString arg1 = QString::fromUtf8(argstrs.at(1).c_str(), argstrs.at(1).size());
    long ref = 0;
    bool ok;
    ref = arg0.toLong(&ok);

    if (!opt || !m_successOpt.contains(opt)) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_SETVALUE_LONG_REF_STRING_VAL, QString::number(-1));
        return;
    }

    long ret = opt->setValue(ref, arg1);
    sendReturnJson(clientid.c_str(), ref, OPERATOR_LONG_SETVALUE_LONG_REF_STRING_VAL, QString::number(ret));
}

void WebSpider::goBack(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 1) {
        RETURN_VOID(clientid.c_str());
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    long ref = 0;
    bool ok;
    ref = arg0.toLong(&ok);

    if (!opt || !m_successOpt.contains(opt)) {
        RETURN_VOID(clientid.c_str());
        return;
    }

    opt->goBack(ref);
    RETURN_VOID(clientid.c_str());
}

void WebSpider::goForward(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 1) {
        RETURN_VOID(clientid.c_str());
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    long ref = 0;
    bool ok;
    ref = arg0.toLong(&ok);

    if (!opt || !m_successOpt.contains(opt)) {
        RETURN_VOID(clientid.c_str());
        return;
    }

    opt->goForward(ref);
    RETURN_VOID(clientid.c_str());
}

void WebSpider::refresh(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 1) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_REFRESH_LONG_REF, QString::number(-1));
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    long ref = 0;
    bool ok;
    ref = arg0.toLong(&ok);

    if (!opt || !m_successOpt.contains(opt)) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_REFRESH_LONG_REF, QString::number(-1));
        return;
    }

    long ret = opt->refresh(ref);
    sendReturnJson(clientid.c_str(), ref, OPERATOR_LONG_REFRESH_LONG_REF, QString::number(ret));
}

void WebSpider::submit(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 1) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_SUBMIT_LONG_REF, QString::number(-1));
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    long ref = 0;
    bool ok;
    ref = arg0.toLong(&ok);

    if (!opt || !m_successOpt.contains(opt)) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_SUBMIT_LONG_REF, QString::number(-1));
        return;
    }

    long ret = opt->submit(ref);
    sendReturnJson(clientid.c_str(), ref, OPERATOR_LONG_SUBMIT_LONG_REF, QString::number(ret));
}

void WebSpider::click(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    QMap<QString, QString> resultMap;
    resultMap.insert("page", QString::number(0));

    if (argstrs.size() < 2) {
        resultMap.insert("error", QString::number(-1));
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_CLICK_LONG_REF, mapToJsonString(resultMap));
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    QString asy = argstrs.at(1).c_str();
    long ref = 0;
    bool sync = false;
    bool ok;
    ref = arg0.toLong(&ok);
    sync = asy.toLong(&ok) == 0 ? false : true;

    if (!opt || !m_successOpt.contains(opt)) {
        resultMap.insert("error", QString::number(-1));
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_CLICK_LONG_REF, mapToJsonString(resultMap));
        return;
    }

    int time = 0;
    int dtime = 0;
    if (argstrs.size() == 4) {
        time = QString(argstrs.at(3).c_str()).toLong(&ok);
    } else if (argstrs.size() == 5) {
        time = QString(argstrs.at(3).c_str()).toLong(&ok);
        dtime = QString(argstrs.at(4).c_str()).toLong(&ok);
    }

    if (sync) {
        WebSpiderSyncRequest *req = NULL;
        QString tbk = argstrs.at(2).c_str();
        bool targetetBlank = false;
        targetetBlank= tbk.toLong(&ok) == 0 ? false : true;
        if (targetetBlank) {
            opt->setRawPageFlag();
            req = WebSpiderRequestManager::instance()->createSyncRequest("", m_name, 100, time, dtime);
            m_syncRawPageLoadMap.insert(long(opt), clientid.c_str());
            opt->click(ref, time, dtime, req);
        } else {
            m_syncLoadMap.insert(opt, clientid.c_str());
            opt->clearParseSuccess();
            opt->clearParsed();
            opt->setSyncLoad();
            opt->click(ref, time);
        }
    } else {
        long ret = opt->click(ref, time);
        resultMap.insert("error", QString::number(ret));
        sendReturnJson(clientid.c_str(), ref, OPERATOR_LONG_CLICK_LONG_REF, mapToJsonString(resultMap));
    }
}

void WebSpider::toggle(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 1) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_TOGGLE_LONG_REF, QString::number(-1));
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    long ref = 0;
    bool ok;
    ref = arg0.toLong(&ok);

    if (!opt || !m_successOpt.contains(opt)) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_TOGGLE_LONG_REF, QString::number(-1));
        return;
    }

    long ret = opt->toggle(ref);
    sendReturnJson(clientid.c_str(), ref, OPERATOR_STRING_GETPROPERTY_LONG_REF_STRING_NAME, QString::number(ret));
}

void WebSpider::focus(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 1) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_FOCUS_LONG_REF, QString::number(-1));
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    long ref = 0;
    bool ok;
    ref = arg0.toLong(&ok);

    if (!opt || !m_successOpt.contains(opt)) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_FOCUS_LONG_REF, QString::number(-1));
        return;
    }

    long ret = opt->focus(ref);
    sendReturnJson(clientid.c_str(), ref, OPERATOR_LONG_FOCUS_LONG_REF, QString::number(ret));
}

void WebSpider::selected(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 1) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_SELECTED_LONG_REF, QString::number(-1));
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    long ref = 0;
    bool ok;
    ref = arg0.toLong(&ok);

    if (!opt || !m_successOpt.contains(opt)) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_SELECTED_LONG_REF, QString::number(-1));
        return;
    }

    long ret = opt->selected(ref);
    sendReturnJson(clientid.c_str(), ref, OPERATOR_LONG_SELECTED_LONG_REF, QString::number(ret));
}

void WebSpider::setSelected(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 2) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_SETSELECTED_LONG_REF, QString::number(-1));
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    QString arg1 = argstrs.at(1).c_str();
    long ref = 0;
    long sel = 0;
    bool ok;
    ref = arg0.toLong(&ok);
    sel = arg1.toLong(&ok);
    bool selected = sel == 0 ? false : true;

    if (!opt || !m_successOpt.contains(opt)) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_SETSELECTED_LONG_REF, QString::number(-1));
        return;
    }

    long ret = opt->setSelected(ref, selected);
    sendReturnJson(clientid.c_str(), ref, OPERATOR_LONG_SETSELECTED_LONG_REF, QString::number(ret));
}

void WebSpider::checked(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 1) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_CHECKED_LONG_REF, QString::number(-1));
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    long ref = 0;
    bool ok;
    ref = arg0.toLong(&ok);

    if (!opt || !m_successOpt.contains(opt)) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_CHECKED_LONG_REF, QString::number(-1));
        return;
    }

    long ret = opt->checked(ref);
    sendReturnJson(clientid.c_str(), ref, OPERATOR_LONG_CHECKED_LONG_REF, QString::number(ret));
}

void WebSpider::setChecked(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 2) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_SETCHECKED_LONG_REF, QString::number(-1));
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    QString arg1 = argstrs.at(1).c_str();
    long ref = 0;
    long sel = 0;
    bool ok;
    ref = arg0.toLong(&ok);
    sel = arg1.toLong(&ok);
    bool selected = sel == 0 ? false : true;

    if (!opt || !m_successOpt.contains(opt)) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_SETCHECKED_LONG_REF, QString::number(-1));
        return;
    }

    long ret = opt->setChecked(ref, selected);
    sendReturnJson(clientid.c_str(), ref, OPERATOR_LONG_SETCHECKED_LONG_REF, QString::number(ret));
}

void WebSpider::selectOptionByIndex(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 2) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_SELECTOPTIONBYINDEX_LONG_REF, QString::number(-1));
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    QString arg1 = argstrs.at(1).c_str();
    long ref = 0;
    long index = 0;
    bool ok;
    ref = arg0.toLong(&ok);
    index = arg1.toLong(&ok);

    if (!opt || !m_successOpt.contains(opt)) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_SELECTOPTIONBYINDEX_LONG_REF, QString::number(-1));
        return;
    }

    long ret = opt->selectOptionByIndex(ref, index);
    sendReturnJson(clientid.c_str(), ref, OPERATOR_LONG_SELECTOPTIONBYINDEX_LONG_REF, QString::number(ret));
}

void WebSpider::stale(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 1) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_STALE_LONG_REF, QString::number(-1));
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    long ref = 0;
    bool ok;
    ref = arg0.toLong(&ok);

    if (!opt || !m_successOpt.contains(opt)) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_STALE_LONG_REF, QString::number(-1));
        return;
    }

    long ret = opt->stale(ref);
    sendReturnJson(clientid.c_str(), ref, OPERATOR_LONG_STALE_LONG_REF, QString::number(ret));
}

void WebSpider::activeElement(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (!opt || !m_successOpt.contains(opt)) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_ACTIVEELEMENT, QString::number(-1));
        return;
    }

    long ret = opt->activeElement();
    sendReturnJson(clientid.c_str(), (long)opt, OPERATOR_LONG_ACTIVEELEMENT, QString::number(ret));
}

void WebSpider::selectFrameByName(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 1) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_SELECTFRAMEBYNAME_STRING_NAME, QString::number(-1));
        return;
    }

    QString arg0 = argstrs.at(0).c_str();

    if (!opt || !m_successOpt.contains(opt)) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_SELECTFRAMEBYNAME_STRING_NAME, QString::number(-1));
        return;
    }

    long ret = opt->selectFrameByName(arg0);
    sendReturnJson(clientid.c_str(), (long)opt, OPERATOR_LONG_SELECTFRAMEBYNAME_STRING_NAME, QString::number(ret));
}

void WebSpider::selectFrameByIdx(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 1) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_SELECTFRAMEBYIDX_LONG_IDX, QString::number(-1));
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    long idx = 0;
    bool ok;
    idx = arg0.toLong(&ok);

    if (!opt || !m_successOpt.contains(opt)) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_SELECTFRAMEBYIDX_LONG_IDX, QString::number(-1));
        return;
    }

    long ret = opt->selectFrameByIdx(idx);
    sendReturnJson(clientid.c_str(), (long)opt, OPERATOR_LONG_SELECTFRAMEBYIDX_LONG_IDX, QString::number(ret));
}

void WebSpider::isVisible(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 1) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_BOOL_ISVISIBLE_LONG_REF, QString::number(-1));
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    long ref = 0;
    bool ok;
    ref = arg0.toLong(&ok);

    if (!opt || !m_successOpt.contains(opt)) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_BOOL_ISVISIBLE_LONG_REF, QString::number(-1));
        return;
    }

    long ret = opt->isVisible(ref);
    sendReturnJson(clientid.c_str(), ref, OPERATOR_BOOL_ISVISIBLE_LONG_REF, QString::number(ret));
}

void WebSpider::drag(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 4) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_DRAG_LONG_REF_INT_TOX_INT_TOY_INT_DURATION, QString::number(-1));
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    QString arg1 = argstrs.at(1).c_str();
    QString arg2 = argstrs.at(2).c_str();
    QString arg3 = argstrs.at(3).c_str();
    long ref = 0;
    int tox = 0;
    int toy = 0;
    int duration = 0;
    bool ok;
    ref = arg0.toLong(&ok);
    tox = arg1.toLong(&ok);
    toy = arg2.toLong(&ok);
    duration = arg3.toLong(&ok);

    if (!opt || !m_successOpt.contains(opt)) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_DRAG_LONG_REF_INT_TOX_INT_TOY_INT_DURATION, QString::number(-1));
        return;
    }

    long ret = opt->drag(ref, tox, toy, duration);
    sendReturnJson(clientid.c_str(), ref, OPERATOR_STRING_GETPROPERTY_LONG_REF_STRING_NAME, QString::number(ret));
}

void WebSpider::getRect(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 1) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_RECT_GETRECT_LONG_REF, "");
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    long ref = 0;
    bool ok;
    ref = arg0.toLong(&ok);

    if (!opt || !m_successOpt.contains(opt)) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_RECT_GETRECT_LONG_REF, "");
        return;
    }

    QRect rect = opt->getRect(ref);
    QString rectJson;
    
    Json::FastWriter writer;
    Json::Value root(Json::objectValue);

    root["x"] = Json::Value((int)rect.x());
    root["y"] = Json::Value((int)rect.y());
    root["width"] = Json::Value((int)rect.width());
    root["height"] = Json::Value((int)rect.height());

    rectJson = writer.write(root).c_str();

    sendReturnJson(clientid.c_str(), ref, OPERATOR_STRING_GETPROPERTY_LONG_REF_STRING_NAME, rectJson);
}

void WebSpider::getAlertText(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 2) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_STRING_GETALERTTEXT_LONG_REF_BOOL_CLR, "");
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    QString arg1 = argstrs.at(1).c_str();
    long ref = 0;
    bool clr = 0;
    bool ok;
    ref = arg0.toLong(&ok);
    clr = arg1.toLong(&ok) == 0 ? false : true;

    if (!opt || !m_successOpt.contains(opt)) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_STRING_GETALERTTEXT_LONG_REF_BOOL_CLR, "");
        return;
    }

    QString alertStr = opt->getAlertText(ref, clr);
    sendReturnJson(clientid.c_str(), ref, OPERATOR_STRING_GETALERTTEXT_LONG_REF_BOOL_CLR, alertStr);
}

void WebSpider::getInnerXml(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 1) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_STRING_GETINNERXML_LONG_REF, "");
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    long ref = 0;
    bool ok;
    ref = arg0.toLong(&ok);

    if (!opt || !m_successOpt.contains(opt)) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_STRING_GETINNERXML_LONG_REF, "");
        return;
    }

    QString xml = opt->getInnerXml(ref);
    sendReturnJson(clientid.c_str(), ref, OPERATOR_STRING_GETINNERXML_LONG_REF, xml);
}

void WebSpider::getOuterXml(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 1) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_STRING_GETOUTERXML_LONG_REF, "");
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    long ref = 0;
    bool ok;
    ref = arg0.toLong(&ok);

    if (!opt || !m_successOpt.contains(opt)) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_STRING_GETOUTERXML_LONG_REF, "");
        return;
    }

    QString xml = opt->getOuterXml(ref);
    sendReturnJson(clientid.c_str(), ref, OPERATOR_STRING_GETOUTERXML_LONG_REF, xml);
}

void WebSpider::setViewportSize(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 2) {
        RETURN_VOID(clientid.c_str());
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    QString arg1 = argstrs.at(1).c_str();
    int w = 0;
    int h = 0;
    bool ok;
    w = arg0.toLong(&ok);
    h = arg1.toLong(&ok);

    if (!opt || !m_successOpt.contains(opt)) {
        RETURN_VOID(clientid.c_str());
        return;
    }

    opt->setViewportSize(w, h);
    RETURN_VOID(clientid.c_str());
}

void WebSpider::getStateInfo(std::string clientid, QList<std::string> &argstrs)
{
    sendReturnJson(clientid.c_str(), 0, OPERATOR_STRING_GETSTATEINFO, QString(CommunKit::getStateInfo().c_str()));
}

void WebSpider::checkAvailable(std::string clientid, QList<std::string> &argstrs)
{
    sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_CHECK_AVAILABLE, QString::number(1));
}

void WebSpider::renderBase64(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (!opt || !m_successOpt.contains(opt)) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_STRING_RENDER_IMAGE_BASE64, "");
        return;
    }

    if (argstrs.size() >= 1) {
        // render element to png.
        QString arg0 = argstrs.at(0).c_str();
        bool ok;
        long ref = arg0.toLong(&ok);
        QString ret = opt->renderBase64(ref);
        sendReturnJson(clientid.c_str(), 0, OPERATOR_STRING_RENDER_IMAGE_BASE64, ret, false);
        return;
    }

    QString ret = opt->renderBase64();
    sendReturnJson(clientid.c_str(), 0, OPERATOR_STRING_RENDER_IMAGE_BASE64, ret, false);
}

void WebSpider::setDestroyTime(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 1) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_SET_DESTROY_TIME, "0");
        return;
    }

    if (!opt || !m_successOpt.contains(opt)) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_SET_DESTROY_TIME, "0");
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    bool ok = false;
    long timeMS = 0;
    timeMS = arg0.toLong(&ok);

    opt->setSelfDestroyTime(timeMS);

    sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_SET_DESTROY_TIME, "1");
}

void WebSpider::scroll(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 2) {
        RETURN_VOID(clientid.c_str());
        return;
    }

    if (!opt || !m_successOpt.contains(opt)) {
        RETURN_VOID(clientid.c_str());
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    QString arg1 = argstrs.at(1).c_str();
    bool ok = false;
    int x = 0;
    int y = 0;
    x = arg0.toLong(&ok);
    y = arg1.toLong(&ok);

    opt->scroll(x, y);
    RETURN_VOID(clientid.c_str());
}

void WebSpider::setAttribute(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 3) {
        RETURN_VOID(clientid.c_str());
        return;
    }

    if (!opt || !m_successOpt.contains(opt)) {
        RETURN_VOID(clientid.c_str());
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    QString attr = argstrs.at(1).c_str();
    QString value = argstrs.at(2).c_str();
    bool ok = false;
    long ref = 0;
    ref = arg0.toLong(&ok);

    opt->setAttribute(ref, attr, value);
    RETURN_VOID(clientid.c_str());
}

void WebSpider::removeAttribute(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 2) {
        RETURN_VOID(clientid.c_str());
        return;
    }

    if (!opt || !m_successOpt.contains(opt)) {
        RETURN_VOID(clientid.c_str());
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    QString attr = argstrs.at(1).c_str();
    bool ok = false;
    long ref = 0;
    ref = arg0.toLong(&ok);

    opt->removeAttribute(ref, attr);
    RETURN_VOID(clientid.c_str());
}

void WebSpider::getChildsByCssSelector(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 2) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_VOID_GETCHILDSBYCSSSELECTOR, arrayToJson(QList<long>()));
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    QString arg1 = QString::fromUtf8(argstrs.at(1).c_str(), argstrs.at(1).size());
    long ref = 0;
    bool ok;
    ref = arg0.toLong(&ok);

    if (!opt || !m_successOpt.contains(opt)) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_VOID_GETCHILDSBYCSSSELECTOR, arrayToJson(QList<long>()));
        return;
    }

    sendReturnJson(clientid.c_str(), ref, OPERATOR_VOID_GETCHILDSBYCSSSELECTOR, arrayToJson(opt->getChildsByCssSelector(ref, arg1)));
}

void WebSpider::getDomTreeSource(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 1) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_STRING_GETDOMTREESOURCE_LONG_REF, "");
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    long ref = 0;
    bool ok;
    ref = arg0.toLong(&ok);

    if (!opt || !m_successOpt.contains(opt)) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_STRING_GETDOMTREESOURCE_LONG_REF, "");
        return;
    }

    sendReturnJson(clientid.c_str(), ref, OPERATOR_STRING_GETDOMTREESOURCE_LONG_REF, opt->getDomTreeSource(ref));

}

void WebSpider::postData(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 1) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_STRING_POSTDATA_LONG_REF, "");
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    long ref = 0;
    bool ok;
    ref = arg0.toLong(&ok);

    if (!opt || !m_successOpt.contains(opt)) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_STRING_POSTDATA_LONG_REF, "");
        return;
    }

    QString ret = opt->postData();
    sendReturnJson(clientid.c_str(), 0, OPERATOR_STRING_METHOD_LONG_REF, ret);
}

void WebSpider::method(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 1) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_STRING_METHOD_LONG_REF, "");
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    long ref = 0;
    bool ok;
    ref = arg0.toLong(&ok);

    if (!opt || !m_successOpt.contains(opt)) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_STRING_METHOD_LONG_REF, "");
        return;
    }

    QString ret = opt->method();
    sendReturnJson(clientid.c_str(), 0, OPERATOR_STRING_METHOD_LONG_REF, ret);
}

void WebSpider::download(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 2) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_DOWNLOAD_LONG_REF, "");
        return;
    }

    QString arg0 = argstrs.at(0).c_str();
    QString arg1 = QString::fromUtf8(argstrs.at(1).c_str(), argstrs.at(1).size());
    long ref = 0;
    bool ok;
    ref = arg0.toLong(&ok);
    int timeout = arg1.toInt(&ok);

    if (!opt || !m_successOpt.contains(opt)) {
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_DOWNLOAD_LONG_REF, "");
        return;
    }

    WebSpiderDownloadRequest *req = new WebSpiderDownloadRequest(opt, clientid.c_str(), m_name, ref, timeout);

    if (argstrs.size() > 2) {
        QString arg2 = argstrs.at(2).c_str();
        req->setContentType(arg2);
    }

    opt->download(ref, req);
}

void WebSpider::mouseMove(Operator *opt, std::string clientid, QList<std::string> &argstrs)
{
    if (argstrs.size() < 1) {
        RETURN_VOID(clientid.c_str());
        return;
    }

    if (!opt || !m_successOpt.contains(opt)) {
        RETURN_VOID(clientid.c_str());
        return;
    }

    if (argstrs.size() == 1) {
        QString arg0 = argstrs.at(0).c_str();
        long ref = 0;
        bool ok;
        ref = arg0.toLong(&ok);
        opt->mouseMove(ref);
    } else if (argstrs.size() == 2) {
        QString arg0 = argstrs.at(0).c_str();
        QString arg1 = argstrs.at(1).c_str();
        int x = 0, y = 0;
        bool ok;
        x = arg0.toInt(&ok);
        y = arg1.toInt(&ok);
        opt->mouseMove(x, y);
    }

    RETURN_VOID(clientid.c_str());
}


void WebSpider::parseAndCallFunc(QString message)
{
    string clientid;
    long pageid = -1;
    long funcid = 0;
    Json::Reader reader;
    Json::Value value;
    Operator *opt = NULL;

    if (!reader.parse(message.toLatin1().constData(), value))
        return;

    if(!value["clientid"].isNull())
        clientid = value["clientid"].asString();

    if(!value["pageid"].isNull()) {
        std::string id = value["pageid"].asString();
        try {
            pageid = boost::lexical_cast<long>(id);
        } catch(boost::exception& e) {
            QString logMessage = "Get pageid error, id:";
            logMessage.append(id.c_str());
            m_logger->error(logMessage);
        }
    }

    if(!value["funcid"].isNull())
        funcid = value["funcid"].asInt();

    opt = (Operator*)pageid;

    QList<string> argstrs;
    for (int i = 0; i < value.size() - 3; i ++) {
        QString arg(QString("arg") + QString::number(i));
        string retstr;
        if (!value[arg.toLatin1().constData()].isNull()) {
            string str = value[arg.toLatin1().constData()].asString();
            Base64Decode(str, &retstr);
            argstrs.insert(i, retstr);
        }
    }
    
    if (!funcid || pageid == -1) {
        RETURN_VOID(clientid.c_str());
        return;
    }

    // self destroy timer is provide to remove long time free page.
    // A page haven't be operated in destroy timeout time while be remove.
    if (pageid != 0 && m_successOpt.contains(opt)) {
        opt->startSelfDestroyTimer();
    }

    switch(funcid) {
    case OPERATOR_VOID_LOADURL_LONG_REF_STRING_ADDRESS_STRING_OPERATION_QMAP_STRING_STRING_HEADERS_STRING_BODYSTRING_STRING_ENCODING:
        loadUrl(clientid, argstrs);
        break;
    case OPERATOR_VOID_SETHTML_LONG_REF_STRING_HTML:
        setHtml(clientid, argstrs);
        break;
    case OPERATOR_VOID_SETSETTING_LONG_REF_STRING_NAME_STRING_SETTING:
        setSetting(clientid, argstrs);
    break;
    case OPERATOR_LONG_CREATE_STRING_USERAGENT :
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_CREATE_STRING_USERAGENT, QString::number(-1));
        break;
    case OPERATOR_LONG_DESTROY_LONG_REF :
        destroy(clientid, argstrs);
        break;
    case OPERATOR_LONG_GET_LONG_REF_STRING_URL :
        get(clientid, argstrs);
        break;
    case OPERATOR_BOOL_SETDATABASEENABLED_LONG_REF_BOOL_ENABLE :
        setDatabaseEnabled(opt, clientid, argstrs);
        break;
    case OPERATOR_STRING_GETTITLE_LONG_REF :
        getTitle(opt, clientid, argstrs);
        break;
    case OPERATOR_STRING_RENDERTREEDUMP_LONG_REF :
        renderTreeDump(opt, clientid, argstrs);
        break;
    case OPERATOR_STRING_GETPAGESOURCE_LONG_REF :
        getPageSource(opt, clientid, argstrs);
        break;
    case OPERATOR_STRING_GETURL_LONG_REF :
        getUrl(opt, clientid, argstrs);
        break;
    case OPERATOR_BOOL_ISJAVASCRIPTENABLED_LONG_REF :
        // Not Implement
        sendReturnJson(clientid.c_str(), 0, OPERATOR_BOOL_ISJAVASCRIPTENABLED_LONG_REF, QString::number(-1));
        break;
    case OPERATOR_VOID_SETJAVASCRIPTENABLED_LONG_REF_BOOL_ENABLE :
        RETURN_VOID(clientid.c_str());
        // Not Implement
        break;
    case OPERATOR_OBJECT_EVALUATEJS_OBJECT_DRIVER_LONG_REF_OBJECTARRAY_ARGUMENTS :
        // Not Implement
        sendReturnJson(clientid.c_str(), 0, OPERATOR_OBJECT_EVALUATEJS_OBJECT_DRIVER_LONG_REF_OBJECTARRAY_ARGUMENTS, "");
        break;
    case OPERATOR_LONG_GETELEMENTBYID_LONG_REF_STRING_QUERY :
        getElementById(opt, clientid, argstrs);
        break;
    case OPERATOR_LONG_SETCOOKIE_LONG_REF_STRING_COOKIES :
        setCookies(opt, clientid, argstrs);
        break;
    case OPERATOR_STRING_COOKIES_LONG_REF :
        cookies(opt, clientid, argstrs);
        break;
    case OPERATOR_VOID_SETFILTERRULE_STRING_RULES:
        setFilterRule(opt, clientid, argstrs);
        break;
    case OPERATOR_LONG_SETCOOKIE_LONG_REF_STRING_COOKIES_STRING_URL:
        setCookiesWithUrl(clientid, argstrs);
        break;
    case OPERATOR_LONG_DELETECOOKIE_LONG_REF_STRING_CNAME :
        deleteCookie(opt, clientid, argstrs);
        break;
    case OPERATOR_LONG_GETELEMENTSBYTAGNAME_LONG_REF_STRING_QUERY :
        getElementsByTagName(opt, clientid, argstrs);
        break;
    case OPERATOR_LONG_GETELEMENTSBYNAME_LONG_REF_STRING_QUERY :
        getElementsByName(opt, clientid, argstrs);
        break;
    case OPERATOR_LONG_GETELEMENTSBYXPATH_LONG_REF_STRING_QUERY :
        getElementsByXpath(opt, clientid, argstrs);
        break;
    case OPERATOR_LONG_GETELEMENTBYCSSSELECTOR_LONG_REF_STRING_QUERY :
        getElementByCssSelector(opt, clientid, argstrs);
        break;
    case OPERATOR_LONG_GETELEMENTSBYCSSSELECTOR_LONG_REF_STRING_QUERY :
        getElementsByCssSelector(opt, clientid, argstrs);
        break;
    case OPERATOR_STRING_GETTAGNAME_LONG_REF :
        getTagName(opt, clientid, argstrs);
        break;
    case OPERATOR_STRING_GETATTRIBUTE_LONG_REF_STRING_NAME :
        getAttribute(opt, clientid, argstrs);
        break;
    case OPERATOR_STRING_GETPROPERTY_LONG_REF_STRING_NAME :
        getProperty(opt, clientid, argstrs);
        break;
    case OPERATOR_STRING_GETTEXT_LONG_REF :
        getText(opt, clientid, argstrs);
        break;
    case OPERATOR_STRING_GETVALUE_LONG_REF :
        getValue(opt, clientid, argstrs);
        break;
    case OPERATOR_LONG_SENDKEYS_LONG_REF_STRING_TYPE_LONG_KEYS :
        sendKeys(opt, clientid, argstrs);
        break;
    case OPERATOR_LONG_TYPE_LONG_REF_STRING_VAL :
        type(opt, clientid, argstrs);
        break;
    case OPERATOR_LONG_SETVALUE_LONG_REF_STRING_VAL :
        setValue(opt, clientid, argstrs);
        break;
    case OPERATOR_VOID_GOBACK_LONG_REF :
        goBack(opt, clientid, argstrs);
        break;
    case OPERATOR_VOID_GOFORWARD_LONG_REF :
        goForward(opt, clientid, argstrs);
        break;
    case OPERATOR_LONG_REFRESH_LONG_REF :
        refresh(opt, clientid, argstrs);
        break;
    case OPERATOR_LONG_SUBMIT_LONG_REF :
        submit(opt, clientid, argstrs);
        break;
    case OPERATOR_LONG_CLICK_LONG_REF :
        click(opt, clientid, argstrs);
        break;
    case OPERATOR_LONG_RESET_LONG_REF :
        // Not Implement
        sendReturnJson(clientid.c_str(), 0, OPERATOR_LONG_RESET_LONG_REF, QString::number(-1));
        break;
    case OPERATOR_LONG_TOGGLE_LONG_REF :
        toggle(opt, clientid, argstrs);
        break;
    case OPERATOR_LONG_FOCUS_LONG_REF :
        focus(opt, clientid, argstrs);
        break;
    case OPERATOR_LONG_SELECTED_LONG_REF :
        selected(opt, clientid, argstrs);
        break;
    case OPERATOR_LONG_SETSELECTED_LONG_REF :
        setSelected(opt, clientid, argstrs);
        break;
    case OPERATOR_LONG_CHECKED_LONG_REF :
        checked(opt, clientid, argstrs);
        break;
    case OPERATOR_LONG_SETCHECKED_LONG_REF :
        setChecked(opt, clientid, argstrs);
        break;
    case OPERATOR_LONG_SELECTOPTIONBYINDEX_LONG_REF :
        selectOptionByIndex(opt, clientid, argstrs);
        break;
    case OPERATOR_LONG_STALE_LONG_REF :
        stale(opt, clientid, argstrs);
        break;
    case OPERATOR_LONG_ACTIVEELEMENT :
        activeElement(opt, clientid, argstrs);
        break;
    case OPERATOR_LONG_SELECTFRAMEBYNAME_STRING_NAME :
        selectFrameByName(opt, clientid, argstrs);
        break;
    case OPERATOR_LONG_SELECTFRAMEBYIDX_LONG_IDX :
        selectFrameByIdx(opt, clientid, argstrs);
        break;
    case OPERATOR_BOOL_ISVISIBLE_LONG_REF :
        isVisible(opt, clientid, argstrs);
        break;
    case OPERATOR_LONG_DRAG_LONG_REF_INT_TOX_INT_TOY_INT_DURATION :
        drag(opt, clientid, argstrs);
        break;
    case OPERATOR_RECT_GETRECT_LONG_REF :
        getRect(opt, clientid, argstrs);
        break;
    case OPERATOR_STRING_GETALERTTEXT_LONG_REF_BOOL_CLR:
        getAlertText(opt, clientid, argstrs);
        break;
    case OPERATOR_STRING_GETINNERXML_LONG_REF:
        getInnerXml(opt, clientid, argstrs);
        break;
    case OPERATOR_STRING_GETOUTERXML_LONG_REF:
        getOuterXml(opt, clientid, argstrs);
        break;
    case OPERATOR_VOID_SETVIEWPORTSIZE_INT_W_INT_H:
        setViewportSize(opt, clientid, argstrs);
        break;
    case OPERATOR_STRING_GETSTATEINFO:
        getStateInfo(clientid, argstrs);
        break;
    case OPERATOR_LONG_CHECK_AVAILABLE:
        checkAvailable(clientid, argstrs);
        break;
    case OPERATOR_STRING_RENDER_IMAGE_BASE64:
        renderBase64(opt, clientid, argstrs);
        break;
    case OPERATOR_LONG_SET_DESTROY_TIME:
        setDestroyTime(opt, clientid, argstrs);
        break;
    case OPERATOR_VOID_SCROLL:
        scroll(opt, clientid, argstrs);
        break;
    case OPERATOR_VOID_SETATTRIBUTE:
        setAttribute(opt, clientid, argstrs);
        break;
    case OPERATOR_VOID_REMOVEATTRIBUTE:
        removeAttribute(opt, clientid, argstrs);
        break;
    case OPERATOR_VOID_GETCHILDSBYCSSSELECTOR:
        getChildsByCssSelector(opt, clientid, argstrs);
        break;
    case OPERATOR_STRING_GETDOMTREESOURCE_LONG_REF:
        getDomTreeSource(opt, clientid, argstrs);
        break;
    case OPERATOR_STRING_POSTDATA_LONG_REF:
        postData(opt, clientid, argstrs);
        break;
    case OPERATOR_STRING_METHOD_LONG_REF:
        method(opt, clientid, argstrs);
        break;
    case OPERATOR_LONG_DOWNLOAD_LONG_REF:
        download(opt, clientid, argstrs);
        break;
    case OPERATOR_VOID_MOUSEMOVE_LONG_REF:
    case OPERATOR_VOID_MOUSEMOVE_INT_X_INT_Y:
        mouseMove(opt, clientid, argstrs);
        break;
    default:
        sendReturnJson(clientid.c_str(), 0, 0, QString::number(0));
        m_logger->error("No Such Operator.");
        break;
    }
}

